<?php

namespace Viettrans\FrontBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Viettrans\FrontBundle\Entity\ServicePro;
use Viettrans\FrontBundle\Form\ServiceProType;

/**
 * ServicePro controller.
 *
 * @Route("/servicepro")
 */
class ServiceProController extends Controller
{
    /**
     * Lists all ServicePro entities.
     *
     * @Route("/", name="servicepro_index")
     * @Template()
     */
    public function indexAction()
    {
        $em = $this->getDoctrine()->getEntityManager();

        $servicepros = $em->getRepository('ViettransFrontBundle:ServicePro')->findAll();

        return array('servicepros' => $servicepros);
    }

    /**
     * Finds and displays a ServicePro entity.
     *
     * @Route("/{id}/show", name="servicepro_show")
     * @Template()
     */
    public function showAction($id)
    {
        $em = $this->getDoctrine()->getEntityManager();

        $entity = $em->getRepository('ViettransFrontBundle:ServicePro')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find ServicePro entity.');
        }

        $deleteForm = $this->createDeleteForm($id);

        return array(
            'entity'      => $entity,
            'delete_form' => $deleteForm->createView(),        );
    }

    /**
     * Displays a form to create a new ServicePro entity.
     *
     * @Route("/new", name="servicepro_new")
     * @Template()
     */
    public function newAction() {
        # Create new instance of class ServicePro, it's just an empty object
        $servicepro = new ServicePro();

		# Set default data
		$servicepro->setTypeId('1');
		
		# If in the user session then auto-fill some fields
		$userId = $this->get('session')->get('userId');
		$user = $this->getDoctrine()->getEntityManager()->getRepository('ViettransFrontBundle:User')->find($userId);
		if ($user) {
			# Auto-fill
			$servicepro->setContactName($user->getName());
			$servicepro->setContactEmail($user->getEmail());
			$servicepro->setContactTelephone($user->getTelephone());
			$servicepro->setLocality($user->getTownObj()->getName().' ('.$user->getTownObj()->getCode().')');
		}
			
        # Get request object
        $request = $this->getRequest();
        
        # Create the form and assign (bind) the form to servicepro object
        $form = $this->createForm(new ServiceProType($this->container), $servicepro);

        # Check if the form is submited
        if ('POST' === $request->getMethod()) {
            # Bind the request to the form
            # !!! Important:
            # All the form fields will be filled with the values in request object
            # Since the form is binded to annoucement object, the corresponding properties of annoucement object will be assigned here
            $form->bindRequest($request);
            
            # Check the form validity
            if ($form->isValid()) {
                # Check form data
                $isEverythingOk = true;
                
                # Check Locality. Format: name (code). Ex: Maison Alfort (94140)
                $locality = $servicepro->getLocality();
                
                # Get entity manager object
                $em = $this->getDoctrine()->getEntityManager();
                
                # Get Repos
                $townRepo = $em->getRepository('ViettransFrontBundle:Town');
                $deptRepo = $em->getRepository('ViettransFrontBundle:Department');
                $catRepo = $em->getRepository('ViettransFrontBundle:Category');
                $typeRepo = $em->getRepository('ViettransFrontBundle:Type');
                
                # Check type
                $type = $typeRepo->find($servicepro->getTypeId());
                
                # If the corresponding type does not exist then show the error
                if (!$type) {
                    $isEverythingOk = false;
                    $form->addError(new FormError('Loại tin không hợp lệ. Bạn phải chọn loại tin trong danh sách.'));
                }
                
                # Check category
                $category = $catRepo->find($servicepro->getCategoryId());
                
                # If the category type is not valid then show the error
                if (!$category || $category->getParentId() == 0) {
                    $isEverythingOk = false;
                    $form->addError(new FormError('Danh mục không hợp lệ. Bạn phải chọn danh mục trong danh sách.'));
                }
                
                # Check locality
                $town = $townRepo->getTownByLocality($locality);

                # If the corresponding town does not exist then show the error
                if (!$town) {
                    $isEverythingOk = false;
                    $form->addError(new FormError('Thành phố không hợp lệ. Bạn phải chọn thành phố trong danh sách gợi ý.'));
                }
                
                # If photo exists then check photo
                $photo = $servicepro->getPhoto();
                if (isset($photo)) {
                    # Size is > 1Mb
                    if ($photo->getSize() > 1000000) {
                        $isEverythingOk = false;
                        $form->addError(new FormError('Kích thước ảnh không được vượt quá 1Mb.'));
                    
                    # Format is not valid
                    } elseif(!in_array($photo->getClientMimeType(), array('image/jpeg', 'image/jpg', 'image/png', 'image/gif'))) {
                        $isEverythingOk = false;
                        $form->addError(new FormError('Định dạng ảnh không hợp lệ (.jpeg .jpg .png .gif).'));
                    }
                }
                
                # If everything is ok then show the preview page
                if ($isEverythingOk) {
                    # Get department id
                    $departmentId = substr($town->getCode(), 0, 2);

                    $servicepro->setTownId($town->getId());
                    $servicepro->setDepartmentId($departmentId);
                    
                    $servicepro->setTypeName($type->getName());
                    $servicepro->setCategoryName($category->getName());
                     
                    # Upload photo if it exists
                    if (isset($photo)) {
                        # Get uploaded photo file and resize it to the big format
                        # then encoded it to base64 and send it to session variable                    
                        $tmpFile = $photo->getPathName();
                        
                        switch ($photo->getClientMimeType()) {
                            case 'image/jpeg':
                            case 'image/jpg':
                                $srcType = 'jpeg';
                                break;
                            case 'image/png':
                                $srcType = 'png';
                                break;
                            case 'image/gif':
                                $srcType = 'gif';
                                break;
                            default:
                                $srcType = 'jpeg';
                                break;
                        }
                        
                        $myImageGenerator = $this->get('my_image_generator');
                    
                        # If there is no error when upload photo then submit the form
                        try {
                            # !Important : convert the photo and set the photodata to $servicepro->photo, so $servicepro->photo is a string
                            # Because when upload, $servicepro->photo is an object, and why a form try to serialize, we'll have the error
                            $photoData = $myImageGenerator->generate(
								$tmpFile,
								$srcType,
								$this->container->getParameter('image_extension'),
								$this->container->getParameter('servicepro_photo_max_width'),
								$this->container->getParameter('servicepro_photo_max_height')
							);
                            
                            # Set the session variable
                            $servicepro->setPhoto(base64_encode($photoData));

                        # If unable to convert the photo then show the error
                        } catch (Exception $e) {
                            $form->addError(new FormError('Có lỗi khi kiểm tra ảnh. Xin vui lòng kiểm tra lại file ảnh.'));
                        }
                    }
                    
                    # If evething is ok then preview
					# If servicepro is posted by user then set userId
					$session = $this->get('session');
					$userId = $session->get('userId');
					if (isset($userId)) $servicepro->setUserId($userId);

                    $session->set('servicepro', $servicepro);
                            
                    return $this->redirect($this->generateUrl('servicepro_preview'));
                }
            }
		}
        
        # Render the corresponding view
        return array(
            'form'       => $form->createView(),
        );
    }

    /**
     * Preview a Servicepro entity.
     *
     * @Route("/preview", name="servicepro_preview")
     * @Template()
     */
    public function previewAction() {
        # Get session object
        $session = $this->get('session');
        
        # If servicepro object is empty then redirect to the new page
        if (!$session->has('servicepro')) {
            return $this->redirect($this->generateUrl('servicepro_new'));
        }
        
        # Get servicepro object via session
        $servicepro = $session->get('servicepro');
        
        # Get the request object
        $request = $this->getRequest();
        
        # Get the method
        $method = $request->getMethod();
        
        # Get the action which is sent via form by post request
        $action = $request->request->get('action');
        
        # Check if the form is submitted, if that is the case then forward to the create page
        if($method == "POST" && $action == "confirm") {
            return $this->redirect($this->generateUrl('servicepro_create'));
        }
        
        # Render the view
        return array(
            'servicepro' => $servicepro,
        );
    }
	
    /**
     * Creates a new ServicePro entity.
     *
     * @Route("/create", name="servicepro_create")
     */
    public function createAction()
    {
        # Get session object
        $session = $this->get('session');

        # If servicepro object is empty then redirect to the new page
        if (!$session->has('servicepro')) {
            return $this->redirect($this->generateUrl('announcement_new'));
        }

        # Get servicepro object via session
        $servicepro = $session->get('servicepro');

        # Get entity manager object
        $em = $this->getDoctrine()->getEntityManager();
        
        # Check if photo exists
        $photo = $servicepro->getPhoto();
        if(isset($photo)) {
            # Generate the photo
            $myImageGenerator = $this->get('my_image_generator');
            
            # Get the image and thumb file path
			$imagesPath = $this->container->getParameter('images_path');
            $randomId = date('Ymdhis').substr(md5(rand(1, 999)), 0, 12);
            $photoFilePath = $imagesPath.'/servicepro/photo/'.$randomId.'.jpg';
            $thumbFilePath = $imagesPath.'/servicepro/thumb/'.$randomId.'.jpg'; 

            try {
                # Generate photo from base64 data to image
                $myImageGenerator->generateFromBase64($servicepro->getPhoto(), $photoFilePath);
                
                # Generate thumb from photo
                $myImageGenerator->generate(
					$photoFilePath,
					$this->container->getParameter('image_extension'),
					$this->container->getParameter('image_extension'),
					$this->container->getParameter('servicepro_thumb_max_width'),
					$this->container->getParameter('servicepro_thumb_max_height'),
					$this->container->getParameter('servicepro_thumb_quality'),
					$thumbFilePath
				);
    
                # Add photo to servicepro
                $servicepro->setPhotos($randomId);
                
            } catch (\Exception $e) {
                # Delete the generated images
                if(file_exists($photoFilePath)) unlink($photoFilePath);
                if(file_exists($thumbFilePath)) unlink($thumbFilePath);
                
                # Remove servicepro object
                $session->remove('servicepro');
                
                $errDetail = '';
                if ($this->container->getParameter('kernel.environment') == 'dev') $errDetail = $e->getMessage();
                
                $session->setFlash('message', 'Có lỗi khi tải ảnh vào hệ thống.'.$errDetail);
                
                return $this->redirect($this->generateUrl('default_error'));
            }
        }
        
        # Persist servicepro to db
        # Begin transaction
		$em->getConnection()->beginTransaction();
		
		try {
            # Persist data to db
            $em->persist($servicepro);
            $em->flush();
    
            # Remove servicepro object
            $session->remove('servicepro');

			# Send activation email
            $message = \Swift_Message::newInstance()
                ->setSubject('Viettrans - Email kích hoạt dịch vụ chuyên nghiệp từ Viettrans.net')
                ->setFrom('no-reply@viettrans.net')
                ->setTo($servicepro->getContactEmail())
                ->setBody($this->renderView('ViettransFrontBundle:Email:activateServicePro.html.twig', array(
                	'contactName'   => $servicepro->getContactName(),
					'name'          => $servicepro->getName(),
					'activationUrl' => $this->generateUrl('servicepro_activate', array(
						'id'    => $servicepro->getId(),
						'token' => $this->generateToken($servicepro->getId()),
					), true),
                )), 'text/html', 'utf-8');
			
			# If send email successfully
			if ($this->get('mailer')->send($message)) {
				# Commit the transaction
				$em->getConnection()->commit();
				$em->close();
				
				# Set flash message
				$session->setFlash('message', '
					Dịch vụ chuyên nghiệp của bạn đã được đăng kí thành công.<br>
					Để kích hoạt dịch vụ của bạn, xin vui lòng kiểm tra email trong hòm thư mà bạn đã đăng kí và làm theo hướng dẫn.
				');

				return $this->redirect($this->generateUrl('default_success'));
			
			# Error when sending the activation email
			} else {
				# Rollback the transaction
				$em->getConnection()->rollback();
				$em->close();
				
				throw new \Exception('Không gửi được email');  
			}
		
		# Catch the errors
        } catch(\Exception $e) {
            $em->close();
			
			# Remove servicepro object
            $session->remove('servicepro');
            
			$errDetail = '';
            if ($this->container->getParameter('kernel.environment') == 'dev') $errDetail = $e->getMessage();
			
            $session->setFlash('message', 'Có lỗi khi đăng kí dịch vụ chuyên nghiệp của bạn. Xin vui lòng liên hệ với admin.'.$errDetail);
                
            return $this->redirect($this->generateUrl('default_error'));
        }
    }

	/**
	 * Activate the servicepro submitted
	 *
	 * @Route("/{id}/{token}", name="servicepro_activate")
	 */
	public function activateAction($id, $token) {
		# Get session object
        $session = $this->get('session');
	
		# Get entity manager object
		$em = $this->getDoctrine()->getEntityManager();
		
		# Token is not valid
		if ($token !== $this->generateToken($id)) {
			$session->setFlash('message', 'Link kích hoạt của bạn không hợp lệ. Xin vui lòng kiểm tra lại thông tin.');
			
			return $this->redirect($this->generateUrl('default_error'));
		
		# Token is valid
		} else {
			# Get servicepro object
			$servicepro = $em->getRepository('ViettransFrontBundle:ServicePro')->find($id);
			
			if (!$servicepro) {
				$session->setFlash('message', 'Dịch vụ cần kích hoạt không tồn tại trong hệ thống.');
				
				return $this->redirect($this->generateUrl('default_error'));
			} 
			
			# If servicepro has been already activated
			$now = new \DateTime();
			if ($servicepro->getIsActivated()) {
				$session->setFlash('message', 'Dịch vụ của bạn đã được kích hoạt.');

				return $this->redirect($this->generateUrl('default_success'));
			
			# Activate the servicepro
			} else {
				try {
					$now = new \DateTime();
					$servicepro->setBeginsAt($now);

					# Get the service_expiration date
					$expirationDate = clone $now;
					$expirationDate->modify('+'.$this->container->getParameter('servicepro_expiration').' day');
					$servicepro->setExpiresAt($expirationDate);

					# Set activated
					$servicepro->setActivatedAt($now);
					$servicepro->setIsActivated(true);

					$em->persist($servicepro);
					$em->flush();

					$session->setFlash('message', 'Dịch vụ của bạn đã được kích hoạt thành công.');

					return $this->redirect($this->generateUrl('default_success'));

				# In case of error
				} catch (\Exception $e) {
					$errDetail = '';
					if ($this->container->getParameter('kernel.environment') == 'dev') $errDetail = $e->getMessage();
				
					$session->setFlash('message', 'Có lỗi không xác định khi kích hoạt dịch vụ của bạn. Xin vui lòng liên hệ với admin.'.$errDetail);
					
					return $this->redirect($this->generateUrl('default_error'));
				}
			}
		}
	}
	
    /**
     * Displays a form to edit an existing ServicePro entity.
     *
     * @Route("/{id}/edit", name="servicepro_edit")
     * @Template()
     */
    public function editAction($id)
    {
        $em = $this->getDoctrine()->getEntityManager();

        $entity = $em->getRepository('ViettransFrontBundle:ServicePro')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find ServicePro entity.');
        }

        $editForm = $this->createForm(new ServiceProType(), $entity);
        $deleteForm = $this->createDeleteForm($id);

        return array(
            'entity'      => $entity,
            'edit_form'   => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        );
    }

    /**
     * Edits an existing ServicePro entity.
     *
     * @Route("/{id}/update", name="servicepro_update")
     * @Method("post")
     * @Template("ViettransFrontBundle:ServicePro:edit.html.twig")
     */
    public function updateAction($id)
    {
        $em = $this->getDoctrine()->getEntityManager();

        $entity = $em->getRepository('ViettransFrontBundle:ServicePro')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find ServicePro entity.');
        }

        $editForm   = $this->createForm(new ServiceProType(), $entity);
        $deleteForm = $this->createDeleteForm($id);

        $request = $this->getRequest();

        $editForm->bindRequest($request);

        if ($editForm->isValid()) {
            $em->persist($entity);
            $em->flush();

            return $this->redirect($this->generateUrl('servicepro_edit', array('id' => $id)));
        }

        return array(
            'entity'      => $entity,
            'edit_form'   => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        );
    }

    /**
     * Deletes a ServicePro entity.
     *
     * @Route("/{id}/delete", name="servicepro_delete")
     * @Method("post")
     */
    public function deleteAction($id)
    {
        $form = $this->createDeleteForm($id);
        $request = $this->getRequest();

        $form->bindRequest($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getEntityManager();
            $entity = $em->getRepository('ViettransFrontBundle:ServicePro')->find($id);

            if (!$entity) {
                throw $this->createNotFoundException('Unable to find ServicePro entity.');
            }

            $em->remove($entity);
            $em->flush();
        }

        return $this->redirect($this->generateUrl('servicepro'));
    }

    private function createDeleteForm($id)
    {
        return $this->createFormBuilder(array('id' => $id))
            ->add('id', 'hidden')
            ->getForm()
        ;
    }
	
	private function generateToken($id) {
		$secret = $this->container->getParameter('secret');
		
		return md5($id.$secret);
	}
}
